#ifndef _MONITOR_CPU_
#define _MONITOR_CPU_

#include <stdio.h>
#include <stdbool.h>
#include <math.h>

struct _GOOMF_device_program_state_struct{
	cl_int level;
};
typedef struct _GOOMF_device_program_state_struct* _GOOMF_device_program_state_ptr;

struct _GOOMF_host_program_state_struct{
	int level;
};
typedef struct _GOOMF_host_program_state_struct* _GOOMF_host_program_state_ptr;

struct _GOOMF_used_params_struct{
	int dummy;
};
//saving state in char: first 6 bits state and last 2 bits type
typedef unsigned char fsm_state;

typedef void (*transition_type)(
		fsm_state* input_state,
		_GOOMF_device_program_state_ptr input_data,
		bool* isPartial,
		struct _GOOMF_used_params_struct*);

transition_type _GOOMF_transitions[1];

//const kernel names
const char* kernel_monitor_alg_finite_gpu = "/home/sun/rithm/test/tss03_out/src/GooMF_GPU_monitor_alg_finite.cl";
const char* kernel_monitor_alg_infinite_gpu = "/home/sun/rithm/test/tss03_out/src/GooMF_GPU_monitor_alg_infinite.cl";
const char* kernel_monitor_alg_partial_gpu = "/home/sun/rithm/test/tss03_out/src/GooMF_GPU_monitor_alg_partial.cl";

//array of property gates
bool property_triggers[1] = {true};

unsigned int getNumOfPartialPredicates(int property_number)
{
	if (property_number == 0) return 0;
	return 0;
}

bool isPropertyPartial(int property_number)
{
	if (property_number == 0) return false;
	return false;
}

void copyProgramState(_GOOMF_device_program_state_ptr ps1, _GOOMF_host_program_state_ptr ps2)
{
	ps1->level = ps2->level;
}

int getNumOfProperties()
{
	return 1;
}

fsm_state getInitialState(int property_number)
{
	if (property_number == 0) return 5;
	return 0;
}

int getNumOfInconclusiveStates(int property_number)
{
	if (property_number == 0) return 1;

	//if specified something else - return total number of inconclusive states
	return 1;
}

unsigned int getStateOrder(unsigned int num_of_prop, fsm_state s)
{
	if (num_of_prop == 0 && s == 5) return 0;
	if (num_of_prop == 0 && s == 3) return 1;

	return 0;
}

fsm_state getStateID(unsigned int num_of_prop, unsigned int o)
{
	if (num_of_prop == 0 && o == 0) return 5;
	if (num_of_prop == 0 && o == 1) return 3;

	return 0;
}

void _GOOMF_fill_program_state(_GOOMF_device_program_state_ptr ps,
	int level)
{
	ps->level = level;

	return;
}

int _GOOMF_set_var(_GOOMF_device_program_state_ptr ps, unsigned int var_order, void* var_value)
{
	switch(var_order)
	{
	case 0: ps->level = *((int*)var_value); break;
	default:
		return -1;
	}

	return 0;
}

void transition0(fsm_state* input_state, _GOOMF_device_program_state_ptr input_data, bool* partial_predicates, struct _GOOMF_used_params_struct* used_params)
{
	//property "[] (c)"
	bool c ;
	int level;
	level = input_data->level;

	c = (level == 1);

	//transition branches
	if( (*input_state == 5) && ( c ))
			*input_state = 5;
	else if( (*input_state == 5) && ( ! c ))
			*input_state = 3;
	else if( (*input_state == 3) && ( c ))
			*input_state = 3;
	else if( (*input_state == 3) && ( ! c ))
			*input_state = 3;
	else return;
}


void initFunctionPointers(transition_type* transitions)
{
	transitions[0] = transition0;
}

int _GOOMF_get_program_state_size()
{
	 return sizeof(cl_int)
	;
}


#endif
